【JS 專案 - 02】 為你的 TodoList 加點函數小菜


Posted by nancy543 on 2021-04-14

接著來到 TodoList v2.0,今天我們來加點函數小菜!
在這可能就有很多初學者跟我一樣的黑人問號??!!

Q1:什麼是函數?什麼是函式?
A1:接下來本篇會教到一個新的名詞和用法,也就是 Function ,台灣翻譯叫「函數」、大陸翻譯「函式」,這裡我們統一以台灣版翻譯為主。

Q2:為何要使用函數(Function)?
A2:大部分的專案裡面都會存在著很多重複性的步驟,以 TodoList 來說:
今天上午新增一個 A、B、C 事項,然後下午修改了 B 事項,後來 A 事項被取消了,所以刪除。隔天在新增 D、E 事項,接著不久又修改 C、D 事項和刪除 E 事項。

(這時候就會看到工程師的經典表情...)
工程師表情包

不論上述事項怎麼增增減減或修改,都還是依循著上一篇提到的5大主功能(儲存、顯示、新增、修改、刪除)在運作,只是把運作中的主角換掉。

如果用原先的程式碼來處理上述的工作,那工程師們可能都想撞牆了,因為都是一堆重複性的工作,無限的複製貼上,程式碼也不知道會爆出幾百幾千行,更別說超難維護與除錯的肥大檔案會造成網頁多大的負擔。既然重工在工程師們的眼裡是個毒瘤,那麼可以解救這些悲慘工程師來處理這些重複性的工作,就是非 Function(函數) 莫屬了。

函數是構成 javascript的基本要素之一。一個函數本身就是一段 JavaScript程式,包含用於執行某一個任務或計算的語法。要呼叫某一個函數之前,你必須先在這個函數想要執行的 scope 中定義它。

簡單來說:
就是把一段或多段的重複指令包起來,等到需要的時候呼叫它,以方便重複執行相同的任務。

所以本篇的學習重點,就是把上一篇的指令全部函數化之後,再呼叫執行而已。


Function(函數) 的宣告方法有好幾種

  1. 函數宣告 Function Declaration
  2. 函數運算式 Function Expression
  3. 函數關鍵字 Function Keyword

這裡僅先以「函數宣告 Function Declaration」來使用和解說,若有興趣研究其他方法的同學請往這走,或是直接拉到文章最下方也有推薦參考文 ↓↓↓↓↓

函數宣告寫法:

function myFunction(){
    .....
}

function 函數名稱 (參數1, 參數2, 參數3, ...) {
  // 要執行的程式代碼
  // 返回值 return
}

JS 白話文:

  • function 來宣告一個函數,後面加上自取的函數名稱(如:myFunctionmyName...)。當然函數也可以沒有名稱,只是寫法不是這樣。沒有名字的函數在 JS 是合法的,通常我們稱它為「匿名函數」,這個暫時不是本文的討論範圍,以後等我心情好XD有空就會另寫一篇關於函數的詳細討論。
  • 小括號 () 中的內容,稱為參數(function parameters),多個參數則用逗號 , 隔開。如果不需要參數,小括號內空白就好,但不可省略,例:function myName()
  • 大括號 {} 內的內容,則是要執行的程式代碼,可用 return 這個功能,來返回指定的值給調用的參數,同時程式也會停止繼續執行,若不用 return 的話則會返回 undefined

說了一堆聽不懂的,還是來個範例比較好理解。下方是早餐店漢堡的食譜,我們寫成函數試試看:

//牛肉漢堡
function HamburgerWithBeef(){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add Beef'; //第三步:牛肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

換成豬肉漢堡試試看:

//豬肉漢堡
function HamburgerWithPork(){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add Pork'; //第三步:豬肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

再換成雞肉漢堡:

//雞肉漢堡
function HamburgerWithChicken(){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add Chicken'; //第三步:雞肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

買尬!如果你是老闆,會不會覺得怎麼那麼煩,有夠多重複的工作方式,如果來個機器人員工幫忙製作就好了...

沒錯,函數就是來解決老闆們的煩惱,讓我們先找出哪裡不一樣!
看來似乎都是肉肉搞的鬼,這些要替換的肉類其實就是我們上面所講到的「參數(function parameters)」,但是參數要放在小括號裡面阿,所以我們稍微修改一下程式內容,把會變動的字改放到小括號內,我們取個參數名叫 meat 好了。

function HamburgerWith(meat){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add' + meat; //第三步:肉肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

宣告完啦!就這麼簡單幾句就可以完成製作各種漢堡的統一條件,但...這只是做完漢堡而已,都還沒到客人手中啊,這時就要用到 呼叫函數 來出餐了。


呼叫函數(Calling function)

宣告完的函數並不會自動的執行,你必須呼叫函數,才會執行函數的內容。

寫法:
函數名稱(參數);

所以做完的漢堡出餐的執行方式就會是這樣...

HamburgerWith(Beef); //牛肉漢堡
HamburgerWith(Pork); //豬肉漢堡
HamburgerWith(Chicken); //雞肉漢堡

以上就是函數的概念,是不是簡單很多。
回到我們的 TodoList 專案,v2.0 版就是把上一篇寫的 code 全部函數化,以方便呼叫重複執行的指令。

先回憶一下上一版 v1.0 的 TodoList 長這樣:

// 1.儲存代辦清單內的陣列資料
var todos = ['item1','item2','item3'];

// 2.顯示代辦清單
console.log(todos);

// 3.新增新的項目
todos.push('newItem');

// 4.更改陣列內的值
todos[0] = 'updated';

// 5.刪除項目
todos.splice(2, 1);

修改為函數化寫法:

1. 儲存代辦清單:
因為是宣告所有的代辦清單,所以這行不用動


2. 顯示代辦清單:

function showTodos() {
    console.log('My todos: ', todos);
};

JS 白話文:

  • 取名一個函數名 showTodos,此項還用不到參數,所以小括號內容空白就好 ()
  • console.log 的內容稍微美化一下,改放字串 'My todos: ' 和變數名 todos,主要是為了讓最後印出的資料看起來更好理解

呼叫函數

showTodos();
  • 因沒設定參數,所以後方的小括號 ();保持空白
  • 印出 My todos: ['item1','item2','item3']

3. 新增新的項目:

function addTodos(newTodos) {
    myTodos.push(newTodos);
    showTodos();
};

JS 白話文:

  • 取名一個函數名 addTodos,小括號內的參數先保持空白(),等下再回頭處理它。
  • 把「1.新增項目」的 myTodos.push('new item'); 那行搬過來。小括號內 'new item' 是會隨著新增的名稱而任意變動,所以並不能以固定字串呈現,所以改為變數並取名為 newTodos。(注意:變數名稱不可加上單引號或雙引號,否則又會變回字串。)
  • 回到上一行 function addTodos(),小括號內的參數要填入剛剛的變數 newTodos,這樣函數內外都有相同變數名稱,才能取值調用,並正確執行函數內容。
  • 下一行加上 showTodos(); 來執行上面的程式。

呼叫函數

addTodos('do my homework');
  • 小括號內並寫入要新增的項目名稱,如'do my homework'
  • 印出 My todos: ['item1','item2','item3', 'do my homework'],可以發現最後面被添加了新的項目 'do my homework'

4. 更改陣列內的值:

function changeTodo (position, updatedName) {
    todos[position] = updatedName;
    showTodos();
};

JS 白話文:

  • 同樣我們並不知道使用者想要修改第幾個代辦事項或改成什麼名稱,於是 function 後的小括號內 2個參數,都要改為變數,參數1(修改位置)取名為 position。參數2(修改後的名稱)取名為 updatedName
  • 把「4.更改陣列」 todos[0] = 'updated'; 那行搬過來。中括號 [0] 內指的是修改位置,和上方的參數1 position 相同,接著 =右方是修改後名稱,也和上方參數2 updatedName相同,這樣才可正確的取到值並調用修改原有的清單項目內容。
  • 下一行加上 showTodos(); 執行程式。

呼叫函數

changeTodo(1, 'take a rest');
  • 小括號內並寫入參數,參數一是數字 1(指的是第二個位置的清單項目 'item2'),參數二是修改後名稱,如 'take a rest.'
  • 如果用 console.log 則印出 My todos: ['item1','take a rest','item3', 'do my homework'],可以發現第二項的 'item2' 已經被修改為 'take a rest'

5. 刪除項目:

function deleteTodo(position) {
    todos.splice(position, 1);
    showTodos();
};

先回憶一下Array的刪除指令用法 .splice(index, howmany, item1, ....., itemX),小括號內包含了:
1.第一個參數 index(必填):指定新增或刪除的序列號碼
2.第二個參數 howmany(選填):從指定新增或刪除的位置起算,共要移除幾筆資料
3.第三個參數 item1,.....,itemX(選填):為新增或修改後的內容(字串要加上單或雙引號),這裡不需要所以不填

JS 白話文:

  • 因為是刪除清單項目,這裡函數 function 的小括號 (),只需要第一個參數值,也就是變數 position,因為沒有要修改或異動項目名稱,當然也就不需要參數2,
  • 為了可以正確取到變數 position 的值,在使用刪除指令時, .splice() 的第 1個參數,就填入這個變數 position,而不是清單項目的位置。
  • 而第二個參數就維持數字 1 不變,因為目前一次只會刪除一個代辦事項。
  • 第三個參數一樣不需要新增或修改,所以不填。
  • 下一行加上 showTodos(); 執行程式。

呼叫函數

deleteTodo(0);
  • 小括號內並寫入參數 0 (指的是刪除第一個位置的清單項目)
  • 如果用 console.log 則印出 My todos: ['take a rest','item3', 'do my homework'] ,可以發現第一項的 'item1' 已經不見了。

終於結束了鬼打牆的程式解說,一樣幫各位統整一下剛剛 v2.0 的程式碼

// 1.儲存代辦清單內的陣列資料
var todos = ['item1','item2','item3'];

// 2.顯示代辦清單
function showTodos() {
    console.log('My todos: ', todos);
};

// 3.新增新的項目
function addTodos(newTodos) {
    myTodos.push(newTodos);
    showTodos();
};

// 4.更改陣列內的值
function changeTodo (position, updatedName) {
    todos[position] = updatedName;
    showTodos();
};

// 5.刪除項目
function deleteTodo(position) {
    todos.splice(position, 1);
    showTodos();
};

這篇我們學習到具名函數的結構和表達方式,以及如何取值調用。不過這裡只是函數領域的冰山一角,它還有很多更細節的領域可以去探索。本文僅提供施作 ToDoList 專案的功能代碼介紹而已,不多詳加贅述關於函數的其他功能,如果你有興趣,可以看下方的參考資料,或是多去爬文了解,也許可以更帶領你增進許多關於函數的知識。

感謝你耐心看完本文,請到後台跟我領取乖寶寶貼紙一枚 =3= 啾

本文學習參考資料:


#javascript #js #todolist #note #初心者







Related Posts

超讚 Deep Learning on 3D object detection 相關教學影片彙整

超讚 Deep Learning on 3D object detection 相關教學影片彙整

Node.js Advanced Interview Questions for Experienced Professionals

Node.js Advanced Interview Questions for Experienced Professionals

Some relative page about the "dependent types"

Some relative page about the "dependent types"


Comments